function sameVnode(oldNode, newNode) {
  return oldNode.key === newNode.key && oldNode.tag === newNode.tag
}
function createComponent(vnode) {
  let i = vnode.data
  if ((i = i.hook) && (i = i.init)) {
    i(vnode)
  }
  if (vnode.componentInstance) {
    return true
  }
}
export function createElm(vnode) {
  // 面试:虚拟节点的实现,如何将虚拟节点生成真实dom
  const {tag, data, children, text, vm} = vnode
  if (!tag) {
    vnode.el = document.createTextNode(text)
  } else {
    if (createComponent(vnode)) {
      return vnode.componentInstance.$el
    }
    vnode.el = document.createElement(tag)
    if (children) {

      children.forEach((child) => {
        try {
          vnode.el.appendChild(createElm(child))
        } catch (e) {
          console.log(e)
        }
      })
    }

    updateProperties(vnode, data)
  }
  return vnode.el
}
function updateProperties(vnode, data) {
  const el = vnode.el
  let newProps = vnode.data || {}
  let oldProps = data || {}
  let newStyle = newProps.style || {}
  let oldStyle = oldProps.style || {}
  for (let key in oldProps) {
    if (!newStyle[key]) {
      el.style[key] = ''
    }
  }
  for (let key in newProps) {
    if (key === 'style') {
      for (let key in newStyle) {
        el.style[key] = newStyle[key]
      }
    } else {
      el.setAttribute(key, newProps[key])
    }
  }
  for (let key in oldStyle) {
    if (!newProps[key]) {
      el.removeAttribute(key)
    }
  }
}
function updateChildren(parent, oldChildren, newChildren) {
  let oldStartIndex = 0
  let oldStartVnode = oldChildren[0]
  let oldEndIndex = oldChildren.length - 1
  let oldEndVnode = oldChildren[oldEndIndex]

  let newStartIndex = 0
  let newStartVnode = newChildren[0]
  let newEndIndex = newChildren.length - 1
  let newEndVnode = newChildren[newEndIndex]
  function makeIndexByKey(children) {
    let map = {}
    children.forEach((item, index) => {
      map[item.key] = index
    })
    return map
  }
  const map = makeIndexByKey(oldChildren)
  while (oldStartIndex <= oldEndIndex && newStartIndex <= newEndIndex) {
    if (!oldStartVnode) {
      oldStartVnode = oldChildren[++oldStartIndex]
    } else if (!oldEndVnode) {
      oldEndVnode = oldChildren[--oldEndIndex]
    } else if (sameVnode(oldStartVnode, newStartVnode)) {
      // 头头比对
      patch(oldStartVnode, newStartVnode)
      oldStartVnode = oldChildren[++oldStartIndex]
      newStartVnode = newChildren[++newStartIndex]
    } else if (sameVnode(oldEndVnode, newEndVnode)) {
      // 尾尾比对
      patch(oldEndVnode, newEndVnode)
      oldEndVnode = oldChildren[--oldEndIndex]
      newEndVnode = newChildren[--newEndIndex]
    } else if (sameVnode(oldStartVnode, newEndVnode)) {
      // 头尾比对
      patch(oldStartVnode, newEndVnode)
      parent.insertBefore(oldStartVnode.el, oldEndVnode.el.nextSibling)
      oldStartVnode = oldChildren[++oldStartIndex]
      newEndVnode = newChildren[--newEndIndex]
    } else if (sameVnode(oldEndVnode, newStartVnode)) {
      // 尾头比对
      patch(oldEndVnode, newStartVnode)
      parent.insertBefore(oldEndVnode.el, oldStartVnode.el)
      oldEndVnode = oldChildren[--oldEndIndex]
      newStartVnode = newChildren[++newStartIndex]
    } else {
      // 乱序比对
      let moveIndex = map[newStartVnode.key]
      if (moveIndex == undefined) {
        // 老的中没有将新元素插入
        parent.insertBefore(createElm(newStartVnode), oldStartVnode.el)
      } else {
        // 有的话做移动操作
        let moveVnode = oldChildren[moveIndex]
        oldChildren[moveIndex] = undefined
        parent.insertBefore(moveVnode.el, oldStartVnode.el)
        patch(moveVnode, newStartVnode)
      }
      newStartVnode = newChildren[++newStartIndex]
    }
  }
  if (newStartIndex <= newEndIndex) {
    for (let i = newStartIndex; i <= newEndIndex; i++) {
      let ele = newChildren[newEndIndex + 1] == null ? null : newChildren[newEndIndex + 1].el
      parent.insertBefore(createElm(newChildren[i]), ele)
    }
  }
  // 乱序比对完去掉多余的老节点
  if (oldStartIndex <= oldEndIndex) {
    for (let i = oldStartIndex; i <= oldEndIndex; i++) {
      let child = oldChildren[i]
      if (child != undefined) {
        parent.removeChild(child.el)
      }
    }
  }
}
export function patch(oldVnode, vnode) {
  if (!oldVnode) {
    return createElm(vnode)
  }
  const isRealElment = oldVnode.nodeType
  if (isRealElment) {
    const elm = createElm(vnode)
    const parentNode = oldVnode.parentNode
    parentNode.insertBefore(elm, oldVnode.nextSibling)
    parentNode.removeChild(oldVnode)
    return elm
  } else {
    if (!sameVnode(oldVnode, vnode)) {
      console.log(createElm(vnode))
      return oldVnode.el.parentNode.replaceChild(createElm(vnode), oldVnode.el)
    }
    // 文本
    let el = (vnode.el = oldVnode.el)
    if (!oldVnode.tag) {
      if (oldVnode.text !== vnode.text) {
        return (el.textContext = vnode.text)
      }
    }
    // 元素
    updateProperties(vnode, oldVnode.data)
    // 儿子
    // 比较孩子节点
    let oldChildren = oldVnode.children || []
    let newChildren = vnode.children || []
    // 新老都有需要比对儿子
    if (oldChildren.length > 0 && newChildren.length > 0) {
      updateChildren(el, oldChildren, newChildren)
      // 老的有儿子新的没有清空即可
    } else if (oldChildren.length > 0) {
      el.innerHTML = ''
      // 新的有儿子
    } else if (newChildren.length > 0) {
      for (let i = 0; i < newChildren.length; i++) {
        let child = newChildren[i]
        el.appendChild(createElm(child))
      }
    }
  }
}
